package com.ksyun.start.camp;

import com.google.gson.Gson;
import com.ksyun.start.camp.model.ApiResponse;
import com.ksyun.start.camp.model.HeartInstance;
import com.ksyun.start.camp.model.ServiceInstance;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import javax.annotation.PreDestroy;
import java.net.InetAddress;

import java.net.UnknownHostException;
import java.time.LocalDateTime;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 服务启动运行逻辑
 */
@Component
@Slf4j
public class ServiceAppRunner implements ApplicationRunner {

    @Autowired
    RestTemplate restTemplate;

    @Value("${spring.application.name}")
    private String serverName;

    @Value("${server.port}")
    private Integer port;

    @Value("${heart.time}")
    private Integer heartTime;

    @Autowired
    private Gson gson;

    private final String REGISTER_URL="http://localhost:8180/api/register";
    private final String SENDBEAT_URL="http://localhost:8180/api/heartbeat";
    private final String UNREGISTER_URL="http://localhost:8180/api/unregister";

    private ScheduledExecutorService executorService;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        // 此处代码会在 Boot 应用启动时执行
        // 开始编写你的逻辑，下面是提示
        InetAddress localHost = InetAddress.getLocalHost();
        String ipAddress = localHost.getHostAddress();
        String serviceId= serverName+"_"+ipAddress+"_"+port;
        // 在注册中心统一为各个参数去初始化时间
        ServiceInstance serviceInstance = new ServiceInstance(serverName,serviceId,ipAddress,port);
        HeartInstance heartInstance = new HeartInstance(serviceId, ipAddress, port);
        // 1. 向 registry 服务注册当前服务
        registerService(serviceInstance);
        // 2. 定期发送心跳逻辑
        executorService = Executors.newSingleThreadScheduledExecutor();
        executorService.scheduleAtFixedRate(() -> sendHeartbeat(heartInstance), heartTime, heartTime, TimeUnit.SECONDS);
    }


    /**
     * 向注册中心注册当前服务
     */
    private void registerService(ServiceInstance serviceInstance) {
        // 发送 HTTP 请求或调用注册中心的注册接口，将 serviceInstance 注册到注册中心
        // 设置请求头
        HttpHeaders headers = new HttpHeaders();
        //在请求体中放入Json类型的参数
        headers.setContentType(MediaType.APPLICATION_JSON); // 设置请求头 Content-Type 为 JSON
        HttpEntity<ServiceInstance> requestEntity = new HttpEntity<>(serviceInstance, headers); // 将请求体 voucherJson 放入 HttpEntity

        // 发送 Post 请求并接收响应
        ResponseEntity<String> responseEntity = restTemplate.exchange(
                REGISTER_URL,
                HttpMethod.POST,
                requestEntity,
                String.class
        );
        log.info("服务注册时间为:{}",LocalDateTime.now());
        String body = responseEntity.getBody();
        log.info(body);
    }

    /**
     * 发送心跳到注册中心
     */
    private void sendHeartbeat(HeartInstance heartInstance) {
        // 发送 HTTP 请求或调用注册中心的心跳接口，发送心跳信息给注册中心
        // 设置请求头
        HttpHeaders headers = new HttpHeaders();
        //在请求体中放入Json类型的参数
        headers.setContentType(MediaType.APPLICATION_JSON); // 设置请求头 Content-Type 为 JSON
        HttpEntity<HeartInstance> requestEntity = new HttpEntity<>(heartInstance, headers); // 将请求体 voucherJson 放入 HttpEntity
        // 发送 Post 请求并接收响应
        ResponseEntity<String> responseEntity = restTemplate.exchange(
                SENDBEAT_URL,
                HttpMethod.POST,
                requestEntity,
                String.class
        );
        String body = responseEntity.getBody();
        log.info("此时心跳发送时间为:{}", LocalDateTime.now());
        log.info(body);

        ApiResponse apiResponse = gson.fromJson(body, ApiResponse.class);
        int code = apiResponse.getCode();
        if(code==503){//当收到了心跳更新失败的响应时，心跳请求停止
            stopHeartbeat();
        }
    }

    private void stopHeartbeat() {
        if (executorService != null) {
            executorService.shutdown();
            log.info("心跳请求已停止");
        }
    }
    /**
     * 发送注销请求到注册中心
     */
    @PreDestroy
    private void unregisterService() throws UnknownHostException {
        InetAddress localHost = InetAddress.getLocalHost();
        String ipAddress = localHost.getHostAddress();
        String serviceId= serverName+"_"+ipAddress+"_"+port;
        ServiceInstance serviceInstance = new ServiceInstance(serverName,serviceId,ipAddress,port);
        // 设置请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<ServiceInstance> requestEntity = new HttpEntity<>(serviceInstance, headers);

        // 发送注销请求
        ResponseEntity<String> response = restTemplate.exchange(
                UNREGISTER_URL,
                HttpMethod.POST,
                requestEntity,
                String.class
        );
        log.info("服务注销时间为:{}", LocalDateTime.now());
        String body = response.getBody();
        log.info(body);
    }
}
